import UIKit
import ESPullToRefresh

private let kBaseHeight: CGFloat = 0.00001;

/// 刷新控件的方向
public enum RefreshOrientation {
    case top
    case left
    case bottom
    case right
}

/// 控件的使用
public enum RefreshFunction {
    case stop
    case remove
    case hidden
}

/// 控件的add
public enum RefreshAddView {
    case collection
    case table
}

open class GroupTableViewConEx<T, HOLDER:IBCellHolder>:
    ViewConEx,
    UITableViewDelegate,
    UITableViewDataSource,
GroupTableViewDelegate {
   
    public typealias TypeCellHolder = HOLDER;
    
    public typealias TypeData = T;
    
    var data: Array<T>?;
    var map: Set = Set<HOLDER>();
    
    var mapTapLsn: Dictionary = Dictionary<TapListener, UIView>();
    
    public lazy var tableView: UITableView = {
        // 自己创建一个table view的环境
        var tv = UITableView(frame: self.getFrame(), style: self.getStyle());
        tv.separatorStyle = UITableViewCellSeparatorStyle.none
        tv.dataSource = self;
        tv.delegate = self;
        tv.backgroundColor = App.config?.tableBgColor
        
        // 循环绑定所有的nib
        let sectionNum = tv.numberOfSections;
        Log.d("sectionNum = \(sectionNum)");
        for section in 0...sectionNum {
            let rowNum = self.numberOfRows(in: section);
            Log.d("rowNum = \(rowNum)");
            for row in 0...rowNum {
                let name = self.getIBName(section: section, row: row);
                tv.register(UINib(nibName: name, bundle: nil), forCellReuseIdentifier: name);
            }
        }
        
        return tv;
    }()
    
    open override func viewDidLoad() {
        initData();
        setNavBar(bar: getNavBar());
        
        self.view.addSubview(tableView);
        setViews();
    }
    
    public func getFrame() -> CGRect {
        return CGRect(x: 0, y: 0, width: ConstantsEx.kScreenWidth, height: ConstantsEx.kScreenHeight - ConstantsEx.kNavBarHeight)
    }
    
    public func getStyle() -> UITableViewStyle {
        return UITableViewStyle.grouped;
    }
    
    public  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return numberOfRows(in: section);
    }
    
    public  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        didSelectRow(section: indexPath.section, row: indexPath.row);
    }
    
    public func numberOfSections(in tableView: UITableView) -> Int {
        return numberOfSections()
    }

    public  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let section = indexPath.section;
        let row = indexPath.row;
        
        let ibName = getIBName(section: section, row: row);
        let reusableCell = tableView.dequeueReusableCell(withIdentifier: ibName);
        
        // 检查类型
        guard let holder = reusableCell as? HOLDER else {
            fatalError("请绑定对应的xib到holder类");
        }
        
        // 判断是否需要初始化
        if !self.map.contains(holder) {
            self.map.update(with: holder);
            initCellForRow(section: section, row: row, with: holder);
        }
        
        refreshCellForRow(section: section, row: row, with: holder);
       
        holder.selectionStyle = .none
        return holder;
    }
    
    public  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//        let ibName = getIBName(section: indexPath.section, row: indexPath.row);
//        return tableView.zz_heightForCellWithIdentifier(ibName, cacheByIndexPath: indexPath, configuration: { (cell) -> () in
//
//            guard let cell = cell as? HOLDER else {
//                return
//            }
//
//            let section = indexPath.section;
//            let row = indexPath.row;
//            self.initCellForRow(section: section, row: row, with: cell);
//            self.refreshCellForRow(section: section, row: row, with: cell);
//        })
        
        return heightOfRows(indexPath.section, indexPath.row)
    }
    
    public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return headOfItem(section);
    }
    
    public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return headOfSectionView(section)
    }
    
    public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return footOfItem(section)
    }

    public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        return UIView()
    }


    public func addESHeaderRefresh() {
        var header: ESRefreshProtocol & ESRefreshAnimatorProtocol
        header = BaseRefreshHeaderAnimator.init(frame: CGRect.zero)
        
        self.tableView.es.addPullToRefresh(animator: header) { [weak self] in
            self?.pullRefresh()
        }
        self.tableView.expiredTimeInterval = TimeInterval(ConstantsEx.kLimitRefresh)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.tableView.es.autoPullToRefresh()
        }
    }
    
    public func addESFooterRefresh() {
        var footer: ESRefreshProtocol & ESRefreshAnimatorProtocol
        footer = BaseRefreshFooterAnimator.init(frame: CGRect.zero)
        
        self.tableView.es.addInfiniteScrolling(animator: footer) { [weak self] in
            self?.loadMore()
        }
        self.tableView.expiredTimeInterval = TimeInterval(ConstantsEx.kLimitRefresh)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.tableView.es.stopLoadingMore()
        }
    }
    
    public func changeESPullToRefresh( _ function: RefreshFunction) {
        switch function {
        case .stop:
            self.tableView.es.stopPullToRefresh()
            self.tableView.es.stopLoadingMore()
            break
        case .remove:
            self.tableView.es.removeRefreshHeader()
            self.tableView.es.removeRefreshFooter()
            break
        case .hidden:
            self.tableView.es.noticeNoMoreData()
            self.tableView.es.resetNoMoreData()
            break
        default:
            break
        }
    }
    
    
    
    public func addPullRefresh(_ orientation:RefreshOrientation){
        switch orientation {
        case .top:
            tableView.sy_header = TextHeaderFooter(orientation: .top, completion: {
                self.pullRefresh()
            })
            break
        case .left:
            tableView.sy_header = TextHeaderFooter(orientation: .left, completion: {
                self.pullRefresh()
            })
            break
        default:
            break
        }
    }
    
    public func addPullRefresh(_ view: UICollectionView, _ orientation: RefreshOrientation){
        switch orientation {
        case .top:
            view.sy_header = TextHeaderFooter(orientation: .top, completion: {
               self.pullRefresh()
            })
            break
        case .left:
            view.sy_header = TextHeaderFooter(orientation: .left, completion: {
                 self.pullRefresh()
            })
            break
        default:
            break
        }
    }
    
    public func addLoadMore(_ orientation :RefreshOrientation){
        switch orientation {
        case .bottom:
            tableView.sy_footer = TextHeaderFooter(orientation: .bottom, completion: {
                self.loadMore()
            })
            break
        case .right:
            tableView.sy_footer = TextHeaderFooter(orientation: .right, completion: {
                self.loadMore()
            })
            break
        default:
            break
        }
    }
    
    public func addLoadMore(_ view : UICollectionView, _ orientation :RefreshOrientation){
        switch orientation {
        case .bottom:
            view.sy_footer = TextHeaderFooter(orientation: .bottom, completion: {
                self.loadMore()
            })
            break
        case .right:
            
            view.sy_footer = TextHeaderFooter(orientation: .right, completion: {
                self.loadMore()
            })
            break
        default:
            break
        }
    }
    
    public func refreshFunction( _ function : RefreshFunction) {
        switch function {
        case .stop:
            tableView.sy_header?.endRefreshing()
            tableView.sy_footer?.endRefreshing()
            break
        case .remove:
            if tableView.sy_footer != nil {
                tableView.sy_footer!.removeFromSuperview()
            }
            if tableView.sy_header != nil {
                tableView.sy_header!.removeFromSuperview()
            }
           
            break
        case .hidden:
            tableView.sy_header?.endRefreshing()
            tableView.sy_footer?.endRefreshing()
            if tableView.sy_footer != nil {
               tableView.sy_footer? .noMoreData()
            }
            break
        default:
            break
        }
    }
  
    public func refreshFunction(_ view : UICollectionView, _ function : RefreshFunction) {
        switch function {
        case .stop:
            view.sy_header?.endRefreshing()
            view.sy_footer?.endRefreshing()
            break
        case .remove:
            view.sy_header!.removeFromSuperview()
            view.sy_footer!.removeFromSuperview()
            break
        case .hidden:
           view.sy_footer?.noMoreData()
            break
        default:
            break
        }
    }
   
    
    
    /*
     以下是opt的实现
     */
    
    open func pullRefresh() {
        
        
    }
    
    open func loadMore() {
        
    }
    
    public func getItem(at index: Int) -> T? {
        if data == nil {
            return nil;
        }
        
        if index < (data?.count)! {
             return data?[index];
        }
        return nil;
    }
    
    public func add(item: T?) {
        if item == nil {
            return;
        }
        
        if data == nil {
            data = Array();
        }
        data?.append(item!);
    }
    
    public func remove(at index: Int) {
        if data != nil {
            data?.remove(at: index);
        }
    }
    
    public func getData() -> Array<T>? {
        return data;
    }
    
    open func getIBName(section: Int, row: Int) -> String {
        fatalError(ConstantsEx.kNoImpl);
    }
    
    open func numberOfRows(in section: Int) -> Int {
        return data == nil ? 0 : data!.count;
    }
    
    open func heightOfRows(_ section: Int, _ row: Int) -> CGFloat {
        return kBaseHeight;
    }
    
    open func headOfItem(_ section: Int) -> CGFloat {
        return kBaseHeight;
    }
    
    open func headOfSectionView(_ section: Int) -> UIView {
        return UIView()
    }

    open func numberOfSections() -> Int {
        return 1;
    }

    open func footOfItem(_ section: Int) -> CGFloat {
        return kBaseHeight
    }

    open func didSelectRow(section: Int, row: Int) {
        
    }
    
    open func initCellForRow(section: Int, row: Int, with holder: HOLDER) {
    }
    
    open func refreshCellForRow(section: Int, row: Int, with holder: HOLDER) {
    }
    
    public final func setOnTapListener(section: Int, row: Int, v: UIView?) {
        if v == nil {
            return;
        }
        
        let gs = v?.gestureRecognizers;
        if gs != nil {
            for g in gs! {
                if let lsn = g as? TapListener {
                    // 已经设置了. 更新一下下标
                    lsn.section = section;
                    lsn.row = row;
                    return;
                }
            }
        }
        
        let tap = TapListener(target: self, action: #selector(actionTap(sender:)));
        tap.bindView = v;
        tap.section = section;
        tap.row = row;
        v?.addGestureRecognizer(tap);
    }
    
    /// 私有方法, 作为点击tap的中转
    ///
    /// - Parameter sender: 传递过来的gesture
    final func actionTap(sender: TapListener) {
        
        onTap(section: sender.section, row: sender.row, v: sender.bindView);
    }
    
    open func onTap(section: Int, row: Int, v: UIView?) {
        
    }
}


class TapListener: UITapGestureRecognizer {
    var section: Int = 0;
    var row: Int = 0;
    var bindView: UIView?;
}

